package ua.lviv.franko.solvers.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFrame;

import org.jzy3d.maths.Range;
import org.jzy3d.plot3d.builder.Mapper;

import ua.lviv.franko.integration.IFunction2D;
import ua.lviv.franko.solvers.stressanalysis.twoDimention.Solver;
import ua.lviv.franko.solvers.stressanalysis.twoDimention.SolverTest;
import ua.lviv.franko.solvers.stressanalysis.twoDimention.fem.AbstractStressElement;
import ua.lviv.franko.solvers.twoDimention.LinearTriangularElement;
import ua.lviv.franko.triangulation.SaveStructures.Node;
import ua.lviv.franko.triangulation.SaveStructures.Triangle;
import ua.lviv.franko.triangulation.SaveStructures.TriangleL;
import ua.lviv.franko.visualisation.Visualise3D;
import ua.lviv.franko.visualisation.jZoneDrawingPanel;

public class TriangularTestSolverStress {

	public static void get(String FilePath, ArrayList<Integer> NodeList1, ArrayList<Integer> NodeList2) throws FileNotFoundException {
		Scanner in = new Scanner((new FileInputStream(FilePath)));
		in.nextInt();
		in.nextInt();
		in.nextInt();
		in.nextInt();
		int n = in.nextInt();
		in.nextInt();
		for (int i = 0; i < n; i++) {
			in.nextInt();
			NodeList1.add(in.nextInt() - 1);
			NodeList2.add(in.nextInt() - 1);
			in.nextInt();
		}
	}

	public static ArrayList<Node> getNodes(String FilePath) throws FileNotFoundException {
		Scanner in = new Scanner((new FileInputStream(FilePath)));
		ArrayList<Node> NodeList = new ArrayList<Node>();
		int n = in.nextInt();
		in.nextInt();
		in.nextInt();
		in.nextInt();
		for (int i = 0; i < n; i++) {
			in.next();
			NodeList.add(new Node((Double.parseDouble(in.next())), (Double.parseDouble(in.next())), (isTrue(Integer.parseInt(in.next()))), i));
			System.out.println(NodeList.get(i).x + "\t" + NodeList.get(i).y);
		}
		return NodeList;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		double k1 = 1;
		double k2 = 0.5;
		double k3 = 0.25;

		IFunction2D f1 = new IFunction2D() {

			@Override
			public double calculate(double x, double y) {

				return 0;
			}

			@Override
			public double calculateDerivatyX(double x, double y) {

				return 0;
			}

			@Override
			public double calculateDerivatyY(double x, double y) {

				return 0;
			}
		};
		IFunction2D f2 = new IFunction2D() {

			@Override
			public double calculate(double x, double y) {

				return 0;
			}

			@Override
			public double calculateDerivatyX(double x, double y) {

				return 0;
			}

			@Override
			public double calculateDerivatyY(double x, double y) {

				return 0;
			}
		};
		ArrayList<AbstractStressElement> elems = new ArrayList<AbstractStressElement>();
		// read elements
		ArrayList<Integer> NodeList1 = new ArrayList<Integer>();
		ArrayList<Integer> NodeList2 = new ArrayList<Integer>();
		ArrayList<Triangle> TrList = null;
		ArrayList<Node> nodeList = null;
		// String FilePath =
		// "C:\\Users\\mark_o\\Documents\\NetBeansProjects\\MySimpleFEM\\New Folder\\New Folder\\New Folder\\123\\tmp";

		String FilePath = "recources/L/a005";
		// String FilePath = "recources/kvadrat/eps3";
		// String FilePath = "C:/Users/mark_o/workspace/MyFEM/New Folder";
		try {
			Scanner in = new Scanner(new FileInputStream(FilePath + "/file.1.ele"));
			TrList = new ArrayList<Triangle>();
			int n = in.nextInt();
			in.nextInt();
			in.nextInt();
			for (int i = 0; i < n; i++) {
				in.next();
				TrList.add(new TriangleL(Integer.parseInt(in.next()) - 1, Integer.parseInt(in.next()) - 1, Integer.parseInt(in.next()) - 1));
			}
			nodeList = getNodes(FilePath + "/file.1.node");
			get(FilePath + "/file.1.poly", NodeList1, NodeList2);

		} catch (FileNotFoundException ex) {
			Logger.getLogger(SolverTest.class.getName()).log(Level.INFO, null, ex);
		}

		for (Iterator<Triangle> iterator = TrList.iterator(); iterator.hasNext();) {
			Triangle triangle = (Triangle) iterator.next();
			LinearTriangularElement element = new LinearTriangularElement(triangle.A(), triangle.B(), triangle.C(), nodeList.get(triangle.A()), nodeList.get(triangle.B()),
					nodeList.get(triangle.C()), k1, k2, k3, f1, f2);
			elems.add(element);
		}


		Solver s = new Solver(nodeList.size(),elems,null);
		s.generate();
		double[] res = s.solve();
		for (int k = 0; k < res.length; k++) {
			System.out.println(res[k]);
		}
		final ArrayList<AbstractStressElement> el = elems;
		final double[] vals = res;

		double maxX = Double.MIN_VALUE, minX = Double.MAX_VALUE, maxY = Double.MIN_VALUE, minY = Double.MAX_VALUE;
		List<Node> resultList = new ArrayList<Node>();
		for (Node n : nodeList) {
			Node newNode = new Node(n.x + vals[n.Number * 2], n.y + vals[n.Number * 2 + 1], n.IsOnBoundery, n.Number);
			maxX = Math.max(maxX, newNode.x);
			maxY = Math.max(maxY, newNode.y);
			minX = Math.min(minX, newNode.x);
			minY = Math.min(minY, newNode.y);
			resultList.add(newNode);
		}

		jZoneDrawingPanel panel = new jZoneDrawingPanel();
		panel.NodeList = resultList;
		panel.TrList = TrList;
		panel.SetParams(maxX, minX, maxY, minY);
		panel.SetCoefs();
		panel.setSize(800, 600);

		panel.setVisible(true);
		JFrame f = new JFrame();
		f.add(panel);
		f.setSize(800, 600);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setVisible(true);

		double ax = -1.5, bx = 1.5, ay = -1.5, by = 2.5;
		System.out.println("=============================================");
		Visualise3D.show(new Mapper() {
			@Override
			public double f(double x, double y) {
				double val = 0.0;
				int i = 0;
				while (val == 0.0 && i < el.size()) {
					val += el.get(i).calculateU(x, y, vals);
					i++;
				}
				System.out.println(x + " " + y + " " + val);
				// return ff.calculateDerivatyY(x, y);//(x, y);
				return val;
			}
		}, new Range(ax, bx), new Range(ay, by));
		System.out.println("=============================================");
		Visualise3D.show(new Mapper() {
			@Override
			public double f(double x, double y) {
				double val = 0.0;
				int i = 0;
				while (val == 0.0 && i < el.size()) {
					val += el.get(i).calculateV(x, y, vals);
					i++;
				}

				// return ff.calculateDerivatyY(x, y);//(x, y);
				System.out.println(x + " " + y + " " + val);
				return val;
			}
		}, new Range(ax, bx), new Range(ay, by));
		System.out.println("=============================================");
	}

	private static boolean isTrue(int s) {
		if (s == 0) {
			return false;
		} else {
			return true;
		}
	}

}
